import java.io.*;
import java.net.*;
import java.util.logging.Level;
import java.util.logging.Logger;

/**
 * <p>Title: WebServer.java</p>
 *
 * <p>Description: This is the main class of the server. This is where
 * everything is instantiated and configured. Here is also where multithreading
 * of the server will occur.</p>
 *
 * <p>Copyright: Copyright (c) 2011</p>
 *
 * <p>Company: </p>
 * @author David Beaver and Aishwarya Iyer
 * @version 1.0
 */

public class WebServer {
    private ServerSocket server;
    private Socket client;
    private BufferedReader input;
    private BufferedOutputStream output;
    private HttpdConf configuration;
    private Request clientRequest;
    private Response serverResponse;

    public WebServer(){
        try{
            System.out.println("Dash webserver running...");
            this.output = null;
            this.configuration = new HttpdConf();
            this.configuration.readHttpd("C:\\httpd.conf");
            this.configuration.readMIME("C:\\mime.types");
            this.server = new ServerSocket(this.configuration.getPort());
            //this.configuration.testPrint();
        }catch(IOException ex){
            System.out.println("Error creating socket");
        }
    }

    /**
    * Here you will create your server, configure all the settings and listen to
    * the port designated within your configuration. Whenever a request comes in,
    * you will need to process that request appropriately and respond as needed.
    *
    * @param args String[]
    */
    
    public static void main(String[] args)  {
        WebServer myServer = new WebServer();
        while(true){
           myServer.processRequests();
        }
    }

    public void processRequests(){
        try {
            client = server.accept();
            clientThread newClient = new clientThread(client, this.configuration);
            newClient.start();
        } catch (IOException ex) {
            System.out.println("Server couldn't handle client request");
        }
    }

    /**
    * Private class used for multithreading
    */
    class clientThread extends Thread {
        private Socket client;
        private BufferedReader input;
        private BufferedOutputStream output;
        private Request clientRequest;
        private Response serverResponse;
        /**
         * Constructor used to start a thread.
         *
         * @param incoming Socket value which designates the socket used by the client
         * @param hcf HttpdConf object created upon server startup.
         */
        public clientThread(Socket incoming, HttpdConf hcf) {
            this.client = incoming;
            this.clientRequest = new Request(hcf); //create a new request for server to process
            this.serverResponse = new Response(hcf,this.client);
            this.input = null;
            this.output = null;
        }

        /**
         * Used to run your server thread. Here is where you will be processing all
         * requests and returning your responses.
         */
        public void run() {
            try {
                input = new BufferedReader(new InputStreamReader(client.getInputStream())); //read the client's http request into a BufferedReader for parsing
                this.clientRequest.parse(input); //parse request and generate response
                try {
                    this.serverResponse.processRequest(clientRequest);
                } catch (InterruptedException ex) {
                    Logger.getLogger(WebServer.class.getName()).log(Level.SEVERE, null, ex);
                }
                this.client.setSoLinger(true, 1000);
                this.output = new BufferedOutputStream(this.client.getOutputStream());
                this.serverResponse.writeOutput(this.output);
                this.output.flush();
                this.client.close();
            } catch (IOException ex) {
                System.out.println("Server encountered error while responding to client");
            }

        }
    }
}